package com.mystack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * @BelongsProject: 逆波兰表达式 计算器
 * @BelongsPackage: com.mystack
 * @Author: 江岸
 * @CreateTime: 2021-01-16 11:09
 * @Description:
 */
public class PoLandNotation {
    public static void main(String[] args) {
        //中缀表达式转为后缀表达式
        //1 + ( ( 2 + 3 ) * 4 ) - 5 => 1 2 3 + 4 * 5
        String str = "1 + ( ( 2 + 3 ) * 4 ) / 5";
        List<String> list = Arrays.asList(str.split(" "));
        System.out.println(list);
        List<String> fun = fun(list);
        System.out.println(fun);
        System.out.println(calculater(fun));

        //逆波兰表达式放入list中(3+4)*5-6
        //4*5-8+60+8/2 => 4 5 * 8 - 60 + 8 2 / +
//        String string = "4 5 * 8 - 60 + 8 2 / +";
//        List<String> strings = Arrays.asList(string.split(" "));
//        String calculater = calculater(strings);
//        System.out.println(calculater);
    }

    //中缀表达式转后缀表达式方法
    public static List<String> fun(List<String> list) {
        //S1栈 => 运算符栈
        Stack<String> s1 = new Stack<>();
        //S2栈，这里使用list，因为无弹栈操作
        ArrayList<String> arr = new ArrayList<>();
        for (String item : list) {
            if (item.matches("\\d+")) {
                //数字直接入arr
                arr.add(item);
            } else if (item.equals("(")) {
                //左边阔号
                s1.push(item);
            } else if (item.equals(")")) {
                //右边阔号
                while (!s1.peek().equals("(")) {
                    //如果是右括号，则依次弹出s1顶端的运算符，并加入arr，知道左括号为止。此时将这一对阔号丢弃
                    arr.add(s1.pop());
                }
                s1.pop();//消除这一对括号
            } else {
                //当item的优先级小于等于s1顶端的优先级时，将s1顶端运算符入arr，再次将item与s1中运算符持续比较
                while (s1.size() != 0 && Operation.getValue(s1.peek())>= Operation.getValue(item)) {
                    arr.add(s1.pop());
                }
                s1.push(item);
            }
        }
        //将s1中剩余运算符加入arr中
        while (s1.size()!=0){
            arr.add(s1.pop());
        }
        return arr;
    }

    public static String calculater(List<String> list) {
        Stack<String> stack = new Stack<>();
        for (String item : list) {
            if (item.matches("\\d+")) {
                //正则表达式匹配整数
                stack.push(item);
            } else {
                //符号
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                if (item.equals("+")) {
                    stack.push(num1 + num2 + "");
                } else if (item.equals("-")) {
                    stack.push(num1 - num2 + "");
                } else if (item.equals("*")) {
                    stack.push(num1 * num2 + "");
                } else {
                    stack.push(num1 / num2 + "");
                }
            }
        }
        String peek = stack.peek();
        return peek;
    }
}

class Operation {
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIY = 2;

    public static int getValue(String str) {
        //其实这里左括号相当于0 这样保证左括号是最低的，不可以被弹出
        int result = 0;
        switch (str) {
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIY;
                break;
            default:
                System.out.println("该符号不存在");
                break;
        }
        return result;
    }

}